package org.fenixsoft.jvm.chapter7.my;

import org.fenixsoft.jvm.util.Fileutil;

import java.io.File;

/**
 * Created by zejian on 2017/6/21.
 * Blog : http://blog.csdn.net/javazejian [原文地址,请尊重原创]
 */
public class FileClassLoader extends ClassLoader {
    private String rootDir;

    public FileClassLoader(String rootDir) {
        this.rootDir = rootDir;
    }

    /**
     * 编写findClass方法的逻辑
     * @param name
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        System.out.println("invoke findClass");
        // 获取类的class文件字节数组
        byte[] classData = getClassData(name);
        if (classData == null) {
            throw new ClassNotFoundException();
        } else {
            //直接生成class对象
            return defineClass(name, classData, 0, classData.length);
        }
    }

    /**
     * 编写获取class文件并转换为字节码流的逻辑
     * @param className
     * @return
     */
    private byte[] getClassData(String className) {
        // 读取类文件的字节
        String path = classNameToPath(className);
        return Fileutil.getFileByte(path);
    }

    /**
     * 类文件的完全路径
     * @param className
     * @return
     */
    private String classNameToPath(String className) {
        return rootDir + File.separatorChar
                + className.replace('.', File.separatorChar) + ".class";
    }

    public static void main(String[] args) throws ClassNotFoundException {
        String rootDir="E:\\Java\\idea project\\UnderstandingTheJvm3\\src";
        String className = "org.fenixsoft.jvm.chapter7.my.DemoObj";
        test2(rootDir, className);
    }

    public static void test2(String rootDir, String className){
        FileClassLoader loader = new FileClassLoader(rootDir);
        FileClassLoader loader2 = new FileClassLoader(rootDir);

        try {
            //加载指定的class文件,调用loadClass()
            Class<?> object1=loader.loadClass(className);
            Class<?> object2=loader2.loadClass(className);

            System.out.println("loadClass->obj1:"+object1.hashCode());
            System.out.println("loadClass->obj2:"+object2.hashCode());

            //加载指定的class文件,直接调用findClass(),绕过检测机制，创建不同class对象。
            /*Class<?> object3=loader.findClass(className);
            Class<?> object4=loader2.findClass(className);

            System.out.println("loadClass->obj3:"+object3.hashCode());
            System.out.println("loadClass->obj4:"+object4.hashCode());*/

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void test1(String rootDir, String className){
        //创建自定义文件类加载器
        FileClassLoader loader = new FileClassLoader(rootDir);

        System.out.println("FileClassLoader classloader -> " + loader.getClass().getClassLoader());

        try {
            //加载指定的class文件
            Class<?> object1 = loader.loadClass(className);

            Object instance = object1.newInstance();

            System.out.println("DemoObj classloader -> " + instance.getClass().getClassLoader());
            System.out.println(instance.toString());

            //输出结果:I am DemoObj
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

